package ru.spbau.krasko.phonelock.settings;

import java.util.Vector;

import ru.spbau.krasko.phonelock.utils.Constants;

import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.CodeModuleManager;
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
import net.rim.device.api.util.Persistable;

public class Settings {
	public static final int LOCK_ON_SLIDER_CLOSE = 0;
	public static final int PROXIMITY = 1;
	public static final int SHOW_TIME = 2;
	public static final int SHOW_DATE = 3;
	public static final int SHOW_BATTERY = 4;
	public static final int ALLOW_SOUND_KEY = 5;
	public static final int ALLOW_CAMERA_KEY = 6;

	private static PersistentObject maskPersist;
	private static PersistentObject iconsPersist;
	private static int[] mask;
	private static Vector[] descriptors = new Vector[2];
	static {
		descriptors[0] = new Vector();
		descriptors[1] = new Vector();
	}

	private static class DescriptorImage implements Persistable {
		public int moduleHandle;
		public int descriptorIndex;
		public int rowIndex;
	}

	public static void serializeDescriptors() {
		DescriptorImage[] serialized = new DescriptorImage[descriptors[0]
				.size() + descriptors[1].size()];
		int cnt = 0;
		for (int i = 0; i < 2; ++i) {
			for (int j = 0; j < descriptors[i].size(); ++j) {
				DescriptorImage image = new DescriptorImage();
				image.rowIndex = i;
				ApplicationDescriptor descriptor = (ApplicationDescriptor) descriptors[i]
						.elementAt(j);
				image.descriptorIndex = descriptor.getIndex();
				image.moduleHandle = descriptor.getModuleHandle();
				serialized[cnt++] = image;
			}
		}
		iconsPersist.setContents(serialized);
		iconsPersist.commit();
	}

	private static void deserializeDescriptors() {
		try {
			DescriptorImage[] serialized = (DescriptorImage[]) iconsPersist
					.getContents();
			if (serialized == null) {
				return;
			}
			descriptors[0].setSize(0);
			descriptors[1].setSize(0);
			outer: for (int i = 0; i < serialized.length; ++i) {
				DescriptorImage image = serialized[i];
				ApplicationDescriptor[] candidates = CodeModuleManager
						.getApplicationDescriptors(image.moduleHandle);
				if (candidates != null) {
					for (int j = 0; j < candidates.length; ++j) {
						if (candidates[j].getIndex() == image.descriptorIndex) {
							descriptors[image.rowIndex]
									.addElement(candidates[j]);
							continue outer;
						}
					}
				}
			}
		} catch (Throwable e) { // clean storage if any troubles
			iconsPersist.setContents(new DescriptorImage[0]);
			iconsPersist.commit();
		}
	}

	static {
		long settingsKey = "phone_lock_mask".hashCode();
		maskPersist = PersistentStore.getPersistentObject(settingsKey);
		mask = (int[]) maskPersist.getContents();
		if (mask == null || !Constants.IS_FULL_VERSION) {
			mask = new int[1];// array is simply a wrapper
			mask[0] = -1;
			maskPersist.setContents(mask);
			resetToDefaults();
		}

		long iconsKey = "phone_lock_icons".hashCode();
		iconsPersist = PersistentStore.getPersistentObject(iconsKey);
		deserializeDescriptors();
	}

	public static boolean isEnabled(int setting) {
		return ((mask[0] >> setting) & 1) == 1;
	}
	
	public static void resetToDefaults() {
		setEnabled(ALLOW_CAMERA_KEY, Constants.IS_FULL_VERSION);
		setEnabled(ALLOW_SOUND_KEY, !Constants.IS_FULL_VERSION);
		setEnabled(LOCK_ON_SLIDER_CLOSE, Constants.IS_FULL_VERSION);
		setEnabled(PROXIMITY, false);
		setEnabled(SHOW_BATTERY, Constants.IS_FULL_VERSION);
		setEnabled(SHOW_DATE, Constants.IS_FULL_VERSION);
		setEnabled(SHOW_TIME, Constants.IS_FULL_VERSION);
	}

	public static void setEnabled(int setting, boolean enabled) {
		if (enabled) {
			mask[0] |= (1 << setting);
		} else {
			mask[0] &= ~(1 << setting);
		}
		maskPersist.commit();
	}

	public static Vector[] getDescriptors() {
		return descriptors;
	}

	public static ApplicationDescriptor[] getAddedApplications() {
		ApplicationDescriptor[] result = new ApplicationDescriptor[descriptors[0]
				.size() + descriptors[1].size()];
		int i = 0;
		for (; i < descriptors[0].size(); ++i)
			result[i] = (ApplicationDescriptor) descriptors[0].elementAt(i);
		for (; i < descriptors[0].size() + descriptors[1].size(); ++i)
			result[i] = (ApplicationDescriptor) descriptors[1].elementAt(i
					- descriptors[0].size());
		return result;
	}

	public static void addApplication(ApplicationDescriptor app) {
		if (descriptors[0].contains(app) || descriptors[1].contains(app))
			return;
		if (descriptors[0].size() < 3)
			descriptors[0].addElement(app);
		else if (descriptors[1].size() < 3)
			descriptors[1].addElement(app);
		serializeDescriptors();
	}

	public static void removeApplication(ApplicationDescriptor app) {
		descriptors[0].removeElement(app);
		descriptors[1].removeElement(app);
		serializeDescriptors();
	}

}
